kexec: Avoid unaligned writes when producing crash info.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 24 Apr 2007 08:48:08 +0000 (09:48 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 24 Apr 2007 08:48:08 +0000 (09:48 +0100)
The alignment of info is 32bits in line with the elf specification.
This means that on 64 bit architectures accessing it directly may
result unaligned access and a panic. I have been experiencing
this on IA64.

It seems that a simple approach of having an crash_xen_info_t on
the stack and simply memcopying it into info at the end alleviates
the problem.

Signed-off-by: Simon Horman <horms@verge.net.au>
xen/common/kexec.c

index 80314a6673b162e8aaaca2829e522db156dd0210..c0fe6d239622d324ffb5f5af970c0fb6807f7e14 100644 (file)
@@ -81,20 +81,25 @@ void kexec_crash_save_cpu(void)
 crash_xen_info_t *kexec_crash_save_info(void)
 {
     int cpu = smp_processor_id();
-    crash_xen_info_t *info = (crash_xen_info_t *)ELFNOTE_DESC(xen_crash_note);
+    crash_xen_info_t info;
+    crash_xen_info_t *out = (crash_xen_info_t *)ELFNOTE_DESC(xen_crash_note);
 
     BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
 
-    info->xen_major_version = xen_major_version();
-    info->xen_minor_version = xen_minor_version();
-    info->xen_extra_version = __pa(xen_extra_version());
-    info->xen_changeset = __pa(xen_changeset());
-    info->xen_compiler = __pa(xen_compiler());
-    info->xen_compile_date = __pa(xen_compile_date());
-    info->xen_compile_time = __pa(xen_compile_time());
-    info->tainted = tainted;
+    memset(&info, 0, sizeof(info));
+    info.xen_major_version = xen_major_version();
+    info.xen_minor_version = xen_minor_version();
+    info.xen_extra_version = __pa(xen_extra_version());
+    info.xen_changeset = __pa(xen_changeset());
+    info.xen_compiler = __pa(xen_compiler());
+    info.xen_compile_date = __pa(xen_compile_date());
+    info.xen_compile_time = __pa(xen_compile_time());
+    info.tainted = tainted;
 
-    return info;
+    /* Copy from guaranteed-aligned local copy to possibly-unaligned dest. */
+    memcpy(out, &info, sizeof(info));
+
+    return out;
 }
 
 void kexec_crash(void)